
package com.be.beadmin.design.impl;

import cn.hutool.core.util.ObjectUtil;
import com.be.beadmin.common.entity.PageEntity;
import com.be.beadmin.common.exception.BeadminException;
import com.be.beadmin.common.utils.JpaQueryBuilder;
import com.be.beadmin.common.utils.JpaQueryBuilderNew;
import com.be.beadmin.common.utils.JpaSortBuilder;
import com.be.beadmin.design.dto.input.*;
import com.be.beadmin.design.dto.output.BopEx;
import com.be.beadmin.design.dto.output.BopTotalEx;
import com.be.beadmin.design.entity.*;
import com.be.beadmin.design.entity.Process;
import com.be.beadmin.design.mapper.BopInfoMapper;
import com.be.beadmin.design.mapper.BopTotalMapper;
import com.be.beadmin.design.mapper.BopTotalMapperEx;
import com.be.beadmin.design.mapper.ProcessMapper;
import com.be.beadmin.design.repository.*;
import com.be.beadmin.design.service.BopTotalService;
import com.be.beadmin.service.service.SerialNumberService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* @description 服务实现
* @author Jiahao Liu
* @date 2023-02-22
**/
@Service
@RequiredArgsConstructor
public class BopTotalServiceImpl implements BopTotalService {

    @Autowired
    private  BopTotalRepository bopTotalRepository;
    @Autowired
    private  BopTotalMapper bopTotalMapper;
    @Autowired
    private  BopTotalMapperEx bopTotalExMapper;


    @Autowired
    private BopInfoRepository bopInfoRepository;

    @Autowired
    private BopInfoMapper bopInfoMapper;

    @Autowired
    private SerialNumberService serialNumberService;

    @Autowired
    private ProcessRepository processRepository;

    @Autowired
    private ProcessMapper processMapper;

    @Autowired
    private StandProductRepository standProductRepository;

    @Autowired
    private StandProductProcessInfoRepository standProductProcessInfoRepository;

    @Override
    public Page<BopTotalEx> getBopTotalByPage(PageEntity pageEntity) {
            Pageable pageable = PageRequest.of(
            pageEntity.getCurrent() -1,
            pageEntity.getPageSize());
            Page<BopTotal> page = bopTotalRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    Predicate pre1 =   JpaQueryBuilderNew.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
                    list.add(pre1);
                    Predicate pre2 = criteriaBuilder.equal(root.get(BopTotal_.delete), 0); //过滤为0
                    list.add(pre2);
                    Predicate[] p = new Predicate[list.size()];
                    List<Order> orders = new ArrayList<>();
                    if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
                        orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
                        criteriaQuery.orderBy(orders);
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(BopTotal_.createTime).as(Date.class)));
                    }
                    return  criteriaBuilder.and(list.toArray(p));
                    }
                    , pageable);
            Page<BopTotalEx> page1 = page.map(bopTotalExMapper::toEntity);
            return page1;

    }

    @Override
    public void addBopTotal(BopTotalDto bopTotalDto) {
            BopTotal result = bopTotalRepository.findBopTotalByIdAndDelete(bopTotalDto.getId(), 0);
            if(ObjectUtil.isNotEmpty(result)) {
                throw new BeadminException("BopTotal不存在,请重新查询");
            }
            BopTotal bopTotal = bopTotalMapper.toEntity(bopTotalDto);
            bopTotalRepository.save(bopTotal);
    }

    @Transactional
    @Override
    public void addBop(BopDto bopDto) {

        BopTotalDto bopTotalDto = bopDto.getBopTotalDto();
        //名称不能重复
        if(bopTotalRepository.findBopTotalByBopNameAndDelete(bopTotalDto.getBopName(),0) != null){
            throw new BeadminException("工艺路径名称重复");
        }

        String prefix = "STD.004.";
        String postfix = serialNumberService.getNextSnByCode("BopCodeSerial");
        String bopCode = prefix + postfix;

        String versionInfo = "1";

        bopTotalDto.setBopCode(bopCode);
        bopTotalDto.setVersionInfo(versionInfo);

        BopTotal bopTotal =bopTotalMapper.toEntity(bopTotalDto);
        bopTotalRepository.save(bopTotal);

        String bopName = bopTotalDto.getBopName();
        String memo = bopTotalDto.getMemo();
        List<String> processIdList = bopDto.getProcessIdList();

        List<ProcessDto> processDtoList = new ArrayList<>();
        for(String processId:processIdList){
            Process process = processRepository.findProcessById(processId);
            processDtoList.add(processMapper.toDto(process));
        }

        for(int i=0;i< processDtoList.size();i++){
            ProcessDto processDto=processDtoList.get(i);
            BopInfoDto bopInfoDto = new BopInfoDto();
            bopInfoDto.setBopCode(bopCode);
            bopInfoDto.setBopName(bopName);
            bopInfoDto.setProcessId(processDto.getId());
            bopInfoDto.setProcessCode(processDto.getProcessCode());
            bopInfoDto.setProcessName(processDto.getProcessName());
            bopInfoDto.setIsProductionProcess(processDto.getIsProductionProcess());
            bopInfoDto.setShowSelfInspection(processDto.getShowSelfInspection());
            bopInfoDto.setSequence(i+1);
            bopInfoDto.setMemo(memo);
            BopInfo bopInfo = bopInfoMapper.toEntity(bopInfoDto);
            bopInfoRepository.save(bopInfo);
        }
    }

    @Override
    public void updateBopTotal(BopTotalDto bopTotalDto) {
            BopTotal bopTotal = bopTotalRepository.findBopTotalById(bopTotalDto.getId());
            bopTotal = bopTotalMapper.toEntity(bopTotalDto);
            bopTotalRepository.save(bopTotal);
    }

    @Override
    @Transactional
    public void updateBop(BopDto bopDto) {
        BopTotalDto bopTotalDto = bopDto.getBopTotalDto();
        BopTotal bopTotal =  bopTotalRepository.findBopTotalByBopCode(bopTotalDto.getBopCode());

        String bopCode = bopTotalDto.getBopCode();
//        bopTotal.setBopCode(bopCode);

        String versionInfo = bopTotal.getVersionInfo();
        int version = Integer.parseInt(versionInfo)+1;
        versionInfo = Integer.toString(version);
        bopTotal.setVersionInfo(versionInfo);

        String bopName = bopTotalDto.getBopName();
        bopTotal.setBopName(bopName);

        String memo = bopTotalDto.getMemo();
        bopTotal.setMemo(memo);
        bopTotal.setIsEnabled(bopTotalDto.getIsEnabled());

        bopTotalRepository.save(bopTotal);

        bopInfoRepository.deleteAllByBopCode(bopCode);
        List<String> processIdList = bopDto.getProcessIdList();

        List<ProcessDto> processDtoList = new ArrayList<>();
        for(String processId:processIdList){
            Process process = processRepository.findProcessById(processId);
            processDtoList.add(processMapper.toDto(process));
        }
        for(int i=0;i< processDtoList.size();i++){
            ProcessDto processDto=processDtoList.get(i);
            BopInfoDto bopInfoDto = new BopInfoDto();
            bopInfoDto.setBopCode(bopCode);
            bopInfoDto.setBopName(bopName);
            bopInfoDto.setProcessId(processDto.getId());
            bopInfoDto.setProcessCode(processDto.getProcessCode());
            bopInfoDto.setProcessName(processDto.getProcessName());
            bopInfoDto.setIsProductionProcess(processDto.getIsProductionProcess());
            bopInfoDto.setShowSelfInspection(processDto.getShowSelfInspection());

            bopInfoDto.setSequence(i+1);

            bopInfoDto.setMemo(memo);
            BopInfo bopInfo = bopInfoMapper.toEntity(bopInfoDto);
            bopInfoRepository.save(bopInfo);
        }

        // 修改 所有使用该条工艺路径的标准柜的工时列表清空 并 生成新的
        List<StandProduct> standProductList = standProductRepository.findStandProductByBopCodeAndDelete(bopCode,0);
        for(StandProduct standProduct:standProductList){
            List<StandProductProcessInfo> standProductProcessInfoList = standProductProcessInfoRepository.findStandProductProcessInfoByStandTypeIdAndDelete(standProduct.getId(),0);
            standProductProcessInfoRepository.deleteAll(standProductProcessInfoList);

            List<BopInfo> bopInfoList = bopInfoRepository.findBopInfosByBopCode(bopCode);
            for(BopInfo bopInfo:bopInfoList){
                StandProductProcessInfo standProductProcessInfo=new StandProductProcessInfo();
                standProductProcessInfo.setStandTypeId(standProduct.getId());
                standProductProcessInfo.setStandTypeCode(standProduct.getStandTypeCode());
                standProductProcessInfo.setStandTypeName(standProduct.getStandTypeName());
                standProductProcessInfo.setStandTypeDesc(standProduct.getStandTypeDesc());

                standProductProcessInfo.setBopCode(bopInfo.getBopCode());
                standProductProcessInfo.setBopName(bopInfo.getBopName());

                standProductProcessInfo.setProcessId(bopInfo.getProcessId());
                standProductProcessInfo.setProcessCode(bopInfo.getProcessCode());
                standProductProcessInfo.setProcessName(bopInfo.getProcessName());
                standProductProcessInfo.setSequence(bopInfo.getSequence());

                standProductProcessInfo.setIsProductionProcess(bopInfo.getIsProductionProcess());
                standProductProcessInfo.setShowSelfInspection(bopInfo.getShowSelfInspection());

                standProductProcessInfo.setStandWorkHour(0);
                standProductProcessInfo.setStandCycle(0);
                standProductProcessInfoRepository.save(standProductProcessInfo);
            }

            standProduct.setState(0);
            standProductRepository.save(standProduct);
        }
    }


    @Override
    public void delBopTotal(String id) {
        BopTotal bopTotal = bopTotalRepository.findBopTotalById(id);
        bopTotal.setDelete(1);
        bopTotalRepository.save(bopTotal);

        String bopCode = bopTotal.getBopCode();
        List<BopInfo> bopInfoList = bopInfoRepository.findBopInfosByBopCode(bopCode);
        for(int i=0;i<bopInfoList.size();i++){
            BopInfo bopInfo = bopInfoList.get(i);
            bopInfo.setDelete(1);
            bopInfoRepository.save(bopInfo);
        }
    }

    @Override
    public void delBopTotals (List<String> ids) { }

    @Override
    public List<BopTotalInfoDto> getBopCodeAndName() {
        List<BopTotalInfoDto> bopList = new ArrayList<>();
        List<BopTotal>  bopTotalList = bopTotalRepository.findAllByIsEnabledAndDelete(1,0);
        for (BopTotal bopTotal : bopTotalList) {
            BopTotalInfoDto bopTotalInfoDto=new BopTotalInfoDto();
            String bopCode = bopTotal.getBopCode();
            String bopName = bopTotal.getBopName();
            bopTotalInfoDto.setBopCode(bopCode);
            bopTotalInfoDto.setBopName(bopName);
            bopList.add(bopTotalInfoDto);
        }
        return bopList;
    }

    @Override
    public BopTotal getBopTotalByBopName(String bopTotalName) {
         BopTotal bopTotal = bopTotalRepository.findBopTotalByBopNameAndDelete(bopTotalName,0);
        return bopTotal;
    }

    @Override
    public List<BopInfo> getBopInfoByBopCode(String bopCode) {
         return bopInfoRepository.findBopInfoByBopCodeOrderBySequence(bopCode);
    }

    @Override
    public BopEx getBopTotalById(String id) {
        if(id==null) throw new BeadminException("未指定工艺路径id");
        BopTotal bopTotal = bopTotalRepository.findBopTotalByIdAndDelete(id,0);
        BopEx bopEx = new BopEx();
        bopEx.setBopTotal(bopTotal);
        List<BopInfo> bopInfoList = bopInfoRepository.findBopInfosByBopCode(bopTotal.getBopCode());
        bopEx.setBopInfoList(bopInfoList);
        return bopEx;
    }

    /**
     * 获取默认工序
     *
     * @return
     */
    @Override
    public BopTotal getDefaultBopTotal() {
        BopTotal bopTotal = null;
        List<BopTotal> bopTotals = bopTotalRepository.findBopTotalByBopNameLikeAndDelete("%标准工艺%", 0);
        if (!bopTotals.isEmpty()) {
            bopTotal = bopTotals.get(0);
        }
        if (bopTotal==null) {
            throw new BeadminException("没有找打默认的工艺路径，请设计人员配置一个默认的工艺路径，名称包含【标准工艺】");
        }
        return bopTotal;
    }

    @Override
    public BopTotal getBopTotalByBopCode(String bopCode) {
        return bopTotalRepository.findBopTotalByBopCode(bopCode);
    }

}